/*
 * Copyright:  2018 smarabbit studio.
 *
 *  Licensed under the Confluent Community License; you may not use this file
 *  except in compliance with the License.  You may obtain a copy of the License at
 *
 *  http://www.confluent.io/confluent-community-license
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 *  WARRANTIES OF ANY KIND, either express or implied.  See the License for the
 *  specific language governing permissions and limitations under the License.
 *
 *  @作   者： 黄开晖 (117227773@qq.com)
 *  @日   期:  2020年9月22日
 */
package com.massyframework.beanskin.launching.web.jetty;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.massyframework.beanskin.SimpleModuleIdentifier;
import com.massyframework.beanskin.StartStopAbility;
import com.massyframework.beanskin.framework.Framework;
import com.massyframework.beanskin.framework.FrameworkConfig;
import com.massyframework.beanskin.framework.FrameworkEventAdapter;
import com.massyframework.beanskin.framework.FrameworkInitializedEvent;
import com.massyframework.beanskin.launching.LaunchingHandler;
import com.massyframework.beanskin.launching.web.FrameworkStartStopListener;
import com.massyframework.beanskin.util.classloading.ClassLoaderUtils;
import com.massyframework.beanskin.util.exceptioncollect.ExceptionCollectUtils;
import com.massyframework.beanskin.util.localstore.LocalStore;



/**
 * Jetty启动器
 * @author huangkh
 *
 */
public class JettyLaunchingHandler implements LaunchingHandler {
	
	private Logger logger = LoggerFactory.getLogger(JettyLaunchingHandler.class);
	private static final String PORT = "jetty.http.port";

	/**
	 * 
	 */
	public JettyLaunchingHandler() {
	}
	
	

	@Override
	public void init(FrameworkConfig config) {
		// 已设置运行环境变量情况下，跳过
		if (config.getParameter(Framework.RUN_ENVIRONMENT) != null) {
			return;
		}
		
		try {
			final Server server =
	                new JettyServerBuilder()
	                        .port(this.getPort(config))
	                        .resourceBase(this.getBaseResource(config))
	                        .build(config);
			config.addBean(Server.class.getName(), server);
			config.addBean(StartStopAbility.class.getName(), new JettyServer(server));
	        config.addListener(new EventListener(server));    
	        
		}catch(Exception e) {
			if (logger.isErrorEnabled()) {
				logger.error(e.getMessage(), e);
			}
			ExceptionCollectUtils.addException(e);
		}
	}

	
	/**
     * 获取端口号
     * @param builder {@link FrameworkBuilder}
     * @return {@link int}
     */
    protected int getPort(FrameworkConfig config){
        return Integer.parseInt(config.getParameter(PORT, "8080"));
    }

    /**
     * 获取webapp文件目录
     * @param plugin {@link Plugin}
     * @return {@link Resource}
     */
    protected String getBaseResource(FrameworkConfig config){
    	LocalStore localstore = config.getBean(LocalStore.class.getName(), LocalStore.class);
    	
    	
		Path path = localstore.getDeploymentDirectory(
				SimpleModuleIdentifier.createModuleIdentifierWithKernel());
		Path webapp = path.resolve(".webapp");
		if (!Files.exists(webapp)) {
			try {
				Files.createDirectories(webapp);
			} catch (IOException e) {
			}
		}
        return webapp.toFile().getAbsolutePath();
    }
    
    public class JettyServer implements StartStopAbility {
    	
    	private Server server;
    	
    	public JettyServer(Server server) {
    		this.server = server;
    	}

		@Override
		public void start() throws Exception {
			this.server.join();			
		}

		@Override
		public void stop() throws Exception {
			this.server.setStopAtShutdown(true);		
		}
    	
    }

    public class EventListener extends FrameworkEventAdapter {
    	
    	private Server server;
    	
    	public EventListener(Server server) {
    		this.server = server;
    	}
    	
    	
		@Override
		public void onEvent(FrameworkInitializedEvent event) {
			ServletContextHandler context = (ServletContextHandler)server.getHandler();
            ClassLoader contextLoader = ClassLoaderUtils.setThreadContextClassLoader(this.getClass().getClassLoader());
            try {
                context.setAttribute(Framework.class.getName(), event.getFramework());
                context.addEventListener(new FrameworkStartStopListener(false));
                server.start();
            } catch (Exception e) {
                e.printStackTrace();
            }finally{
                Thread.currentThread().setContextClassLoader(contextLoader);
            }
		}		
    }
}
